

/Radius of shield detection area. Multiplay value below by 2.5 for TA pixel radius.

#define UPGRADE_RADIUS [410]




FirePrimary()		|  actually fires a shot. As you see, it's by default programmed to show
	{		|  the flare, then to "sleep" - doing absolutely nothing in this sub-
	show RFlare;	|  script (well, if the unit is walking and shooting, only the shooting
	sleep 150;	|  will pause while it continues to move as nothing happened) and then 
	hide RFlare;	|  hide the flare again. The sleep is scaled in milliseconds, so you
	return(0);	|  see the flare for 0.15 second exactly.
	}


AimPrimary(heading,pitch)
	{
	signal SIG_AIM1;
	set-signal-mask SIG_AIM1;
	var count;
	count = 0;
	While(( heading > 24576 ) && ( heading < 40960 ))
		{
		sleep 150;
		count = count + 1;
		If( count == 20 )
			{
			signal SIG_AIM1;
			--
		--
	//Turret animations
	return(TRUE);
	--




TurnControl()
	{
	var CurrentPosit, LastPosit, ShortDiff, ShortAngle, TurnAngle;

	CurrentPosit = InitPosit; // Sets the current and last position to the point where
	LastPosit = InitPosit;    // the unit is built, it will use this as a frame of reference
	while (TRUE)
		{
		sleep 500; 
		// have to put a pause, or it eats processor cycles like crazy

		CurrentPosit = get Piece_XZ (base); 
		// sets the current position to the unit's XZ map location

		if (LastPosit == CurrentPosit) // if the unit hasn't moved since the last check
			{
			// Put the script for returning the pieces to their original position here.
			--

		if (LastPosit != CurrentPosit)
			{
			ShortDiff = CurrentPosit - LastPosit; 
			// A funtion of TA scripting, gets the distance between two points on a map.

			ShortAngle = get XZ_ATAN(ShortDiff); 
			// gets the ArcTangent of the above distance (TA assumes the distance
			// is the hypotenuse of a right triangle).

			TurnAngle = ShortAngle + 180;
			// necessary because the angle it returns is 180 degrees off.

			TurnAngle = TurnAngle * 4;
			// I'm not sure why these two lines are in here...
			TurnAngle = 0 - TurnAngle;
			// ...but it makes it work, so I leave them alone

			// Put the script for turning the pieces here, using the TurnAngle variable. 
			// (fex: turn rudder1 to y-axis TurnAngle speed [50];)
			--
		LastPosit = CurrentPosit; // sets the last known position, which was the current
					  // position on the previous run-through.
		--
	--

Create()
	{
	InitPosit = get Piece_XZ (base); 
	// This sets the initial position of the unit, only checked once by the TurnControl script

	while (get BUILD_PERCENT_LEFT > 0)
		{
		sleep 1000; // Wait for it... Wait for it...
		--
	start-script TurnControl(); // Go! :P



Bigfoot Wheel script.

Code:

Monitor()
	{
	var lastcheck, check;

	lastcheck = 0;
	check = 0;
	while(TRUE)
		{
		sleep 100; // a delay, so the engine doesn't choke.
		check = check + 1; // time the delay between shots
		if (firecheck != lastcheck) // if weapon has been fired...
			{
			if (check < 14) // change this number to 1/10 of reload
					// in weapon .tdf file.
				{
				// place changes to unit here, fex additional weapons,
				// ARMORED on, ACTIVATION on (radar/jamming), or just
				// more pieces on the model, for decoration.
				return(0); // kills the script after this happens.
				--
			check = 0; // "resets the clock" each time weapon is fired.
			--
		lastcheck = firecheck; // if the weapon is not fired, run the clock.
		--
	--

Create()
	{
	firecheck = 0;
	start-script Monitor();
	--

FirePrimary()
	{
	firecheck = !firecheck; // this signals "Monitor()" that the weapon has been fired.
	return(0);
	--
Detection of Veteran Status.

Code:

static-var Go_Jump;

MoveRate2()
	{
	Go_Jump = 1;
	return(0);
	--

MoveRate1()
	{
	Go_Jump = 0;
	return(0);
	--

JumpControl()
	{
	var front_height, main_height;

	while(TRUE)
		{
		sleep 250;
		if (Go_Jump)
			{
			front_height = get GROUND_HEIGHT( get PIECE_XZ(frontpiece));
			main_height = get GROUND_HEIGHT( get PIECE_XZ(base));
			if (front_height < main_height)
				{
				//animation code
				--
			--
		--
	--

Create()
	{
	Go_Jump = 0;
	while (get BUILD_PERCENT_LEFT)
		{
		sleep 1000;
		--
	start-script JumpControl();
	--



piece Flare1, Flare2, ... ;

static_var fire, ...;

Create()
	{
	...
	...
	fire = 0;
	--

QueryPrimary (piecenum)
	{
	piecenum = fire
	--

FirePrimary()
	{
	if (!fire)
		{
		show Flare1;
		Move Barrel1 to z-axis [-6] speed [500];
		Wait-for-move Barrel1 along z-axis;
		Move Barrel1 to z-axis [0] speed [5];
		sleep 100;
		hide Flare1;
		--
	if (fire)
		{
		show Flare2;
		Move Barrel2 to z-axis [-6] speed [500];
		Wait-for-move Barrel2 along z-axis;
		Move Barrel2 to z-axis [0] speed [5];
		sleep 100;
		hide Flare2;
		--
	fire = !fire
	--





Script controlled slope adjustment: Upright legs, leaned body



In the /Units/*.fbi
Upright=1; //meaning the engine keep the unit vertical no matter the ground slope.



In the script:

SlopeAdjust()
{
while(TRUE)
{

//Slope measuring formula (The important line!)
orientation=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(foot1))) - (get GROUND_HEIGHT(get PIECE_XZ(foot4)))),((get XZ_HYPOT( ((get PIECE_XZ(foot1)) - (get PIECE_XZ(foot4)))))));

Turn body to x-axis 0 - orientation now;
Turn leg1 to x-axis orientation now;
Turn leg2 to x-axis orientation now;
Turn leg3 to x-axis orientation now;
Turn leg4 to x-axis orientation now;

if (orientation<=32767)
{
Turn neck to x-axis orientation/2 now;
Turn head to x-axis orientation/2 now;

if (orientation>32767)
{
Turn neck to x-axis (65536+orientation)/2 now;
Turn head to x-axis (65536+orientation)/2 now;


sleep 100;




Create()
{
hide flare1;
etc...

start-script SlopeAdjust();




Comments:
- As you can see by reading the above code, the slope is measured by the script, here at the pieces feet1 and feet4, but you can change them to other pieces, just use one piece at the front and another at the end.
- Once changing the piece offset in 3DoBuiler didn't change the measuring point and I had to click "Use current position as Object Origin". But maybe I'm wrong on that point.
- If you experience shakiness, you can damp it by having the "turn" command use a "speed" instead of being instantaneous.
- Unlike the below example, legs usually have walking animation, so either make "orientation" global and use it as an offset to your current leg1 ... leg4 x-axis turn, or add an intermediate piece without any faces between the body and each pair of leg.
- The thing inside the "if" is only for having a split the rotation between neck and head. Angles are not signed, but between 0 and 65535, so what we would think to be a negative angle alpha has in fact a value of 65536-alpha. So I had to separated the two cases for the division by two to work as it should. And as far I know there's no "else" in TA scripting.

The script in action: (on an unreleased AT-AT stolen from the SWTA team) 






Script controlled slope adjustment:
Floating amphibious vehicle than lean on slopes
Featuring SetSFXOccupy partial explanation

In the /Units/*.fbi:
Upright=1;
canhover=1
MovementClass=TANKHOVER3;
(basically it's a pelican .fbi)


In the script:

SlopeAdjust()
{
var x-slope, z-slope;
while(TRUE)
{
if (!overwater)
{
x-slope=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(rearwheels))) - (get GROUND_HEIGHT(get PIECE_XZ(frontwheels)))),((get XZ_HYPOT( ((get PIECE_XZ(rearwheels)) - (get PIECE_XZ(frontwheels)))))));
z-slope=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(right_point))) - (get GROUND_HEIGHT(get PIECE_XZ(left_point)))),((get XZ_HYPOT( ((get PIECE_XZ(right_point)) - (get PIECE_XZ(left_point)))))));
Turn GP to x-axis x-slope now;
Turn GP to z-axis z-slope now;

if (overwater)
{
Turn GP to x-axis 0 now;
Turn GP to z-axis 0 now;

sleep 100;





setSFXoccupy(setSFXoccupy_rawlocvar)
{
// 0 -> Transported: Unit is being loaded
// 1 -> Sea: Unit does not have upright=1 and is going into sea. Or unit has upright=1 and is going into shore. (From unloading, or ground, or deep sea for upright unit)
// 2 -> Sea: Unit has upright=1 and goes into deep sea. (From shore, or unloading)
// 3 -> ????
// 4 -> Land: Unit is being created, goes from sea (or shore if upright=1) to dry ground, or is unloaded

// I dunno if shore stand for shallow water or low level ground.

If(setSFXoccupy_rawlocvar==0)// Transported
{
Overwater=0;

If(setSFXoccupy_rawlocvar==1)// Sea (any sea for not upright, shore for uprigh)
{
Overwater=1;

If(setSFXoccupy_rawlocvar==2)// Sea (deep sea, only used by upright)
{
Overwater=1;

If(setSFXoccupy_rawlocvar==3)// ??
{
Overwater=1;

If(setSFXoccupy_rawlocvar==4)// Land
{
Overwater=0;

return (0);




Create()
{
overwater=0;
start-script SlopeAdjust();
......




Comments:
- The piece frontwheels, rearwheels, left_point, right_point must be created in the .3do as their name imply.
- Yes, current bug is that the green selection square stay upright, while it shoudln't, I don't have a solution for that right now.
- Technically, if the measuring points are children of the base, and you turn the base, the measuring point move a bit, so the ground isn't measured on the very exact same location. This could lead to some instability, some oscillation. You could use some "speed" in the turn to slow down the leaning so as to make the unit still oscillate to show uneveness of terrain, but slowly and not at a flickering rate, or you could just turn not the base, but a piece child of the base, from where everything visible is fixed, but not the measuring point fixed on a still base. Anyway I've obsverd this kind of oscillation only once, and it was with a split-pixel range, and looked actually cute, like if texturing were wavering.



Results:
- Float on water, as opposed to rolling on the seafloor.
- Does not wobble.
- Yet lean accuratly when on ground when on hill.






Unit to investigate setSFXoccupy or any script value you wish

Yes, it's based on my Data-Fetching Tank, because the whole point of that tank was to ease unit-making TA scripting researches. When I made that tank, I left 3 unused variable, called dummy_var1, dummy_var2, dummy_var3 in the script, but var1, var2, var3 ingame, that were already implemented in the menu but linked to nothing, for later use, because I knew I surely missed to allow to show/write some variables that could be important for some scripts.

So, when I started wanting to know about the setSFXoccupy value argument, instead of having to implement a new button in the complex inunits menus, I just used those vars!

Changes since Bridodon9:
- Declared the setSFXoccupy function.
- Everytime the setSFXoccupy function is called, the tank eject a turret (my way to show something is being done, and how many time), and write the setSFXoccupy argument value into dummy_var1, the previous value being passed to dummy_var2, and the penultimate value being passed to dummy_var3.
- That way:
on/off -> read self -> var1 show the last/current setSFXoccupy argument value
on/off -> read self -> var2 show the value it had before
on/off -> read self -> var3 show the value it had even before earlier
- Tank has been changed to display var1 by default
- A bug has been found that resulted in the freezing of the number-display while going past menu1. The cause was that signal are limited to 7~8 : killing 256 also kills 128. To fix that bug, I removed the use of signal to kills the help popups. That mean that now they take some time to die (12sec at most), and are only created by menu1 and menu4.
- The tank has been made amphibious, with a pelican-style .fbi
- The custom weapon has been removed for enhanced compatibility
- A SlopeAdjust script has been added so that it keeps leaning on slope on dry ground with a upright=1. Unlike the script used on FLOZi unit in previous post, this time the measure points are placed in x instead of +, so I calculated slope sides for both parallel direction pairs and used some mean values. But because ATAN returns angle in the +0 +65535 range instead of the -32767 +32768 range, I had to turn angle over 180 into their negative equivalent for the avering to work. (Yes, dividing angles doesn't work if you don't take that precaution. Remember that in your scripts!)

SlopeAdjust()
{
var x-slope, z-slope, x-slope-left, z-slope-front, x-slope-right, z-slope-rear, front_left, front_right, rear_left, rear_right;
front_left=flash_light1;
front_right=flash_light2;
rear_left=flash_light3;
rear_right=flash_light4;

while(TRUE)
{
if (!overwater)
{
x-slope-left=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(rear_left))) - (get GROUND_HEIGHT(get PIECE_XZ(front_left)))),((get XZ_HYPOT( ((get PIECE_XZ(rear_left)) - (get PIECE_XZ(front_left)))))));
x-slope-right=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(rear_right))) - (get GROUND_HEIGHT(get PIECE_XZ(front_right)))),((get XZ_HYPOT( ((get PIECE_XZ(rear_right)) - (get PIECE_XZ(front_right)))))));

z-slope-front=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(front_right))) - (get GROUND_HEIGHT(get PIECE_XZ(front_left)))),((get XZ_HYPOT( ((get PIECE_XZ(front_right)) - (get PIECE_XZ(front_left)))))));
z-slope-rear=get ATAN (((get GROUND_HEIGHT(get PIECE_XZ(rear_right))) - (get GROUND_HEIGHT(get PIECE_XZ(rear_left)))),((get XZ_HYPOT( ((get PIECE_XZ(rear_right)) - (get PIECE_XZ(rear_left)))))));

//Because the result from ATAN does not use -180 180 but 0 360, so for instance -1 is 359, so change them to go back in the -180 180 range for the mean(a1,a2)=(a1+a2)/2 to work
if (x-slope-left>=32768)
{x-slope-left=x-slope-left -65536;
if (x-slope-right>=32768)
{x-slope-right=x-slope-right -65536;
if (z-slope-front>=32768)
{z-slope-front=z-slope-front -65536;
if (z-slope-rear>=32768)
{z-slope-rear=z-slope-rear -65536;


x-slope=(x-slope-left + x-slope-right)/2;
z-slope=(z-slope-front + z-slope-rear)/2;

Turn base to x-axis x-slope now;
Turn base to z-axis z-slope now;

if (overwater)
{
Turn base to x-axis 0 now;
Turn base to z-axis 0 now;

sleep 100;



create and setSFXoccupy like in previous post

So, in short, the following can be used to constantly see the value of the argument of setSFXoccupy by anyone without any knowledge needed, but it is also my currently most scripted unit, using so many script tricks that I can't explain them all: destroyable turret, damage inversion device, in-unit GUI, with horizontally stabilized menu, 10 digit display, temporarily disablable gun, scripted slope leaning, etc.. etc.. etc.. Read there for a brief general idea. Look at he .bos inside the .ufo if you feel like you can handle 1785 lines of code. Ask me while I'm around if you can't understand some points. And just use the in-unit menu and digital-display to check variable behaviors on the fly, without bothering to fully understand how my script works. 







Make a script like that:

piecebase, aiming_base, rotative_base, leaning_base, view_FD00, view_FD01, view_FD02, view_FD03, view_FD04, view_FD05, view_FD06, view_FD07, view_FD08, view_FD09, view_FD10, view_FD11, view_FD12, view_FD13, view_FD14, view_FD15, firing_point, measure_point;

static-var restore_delay, targeting_orientation;

#define SIG_AIM1 2 // signal must be 2 4 8 16 32 64 128

#include "exptype.h"
#define SMOKEPIECE1 base
#include "smokeunit.h"
#include "hitweap.h"
#include "rockunit.h"

#define amount_of_view 16


TwoDimensionnal()
{
var orientation, view_to_show;

turn leaning_base to x-axis <26.565> now; // TA view angle is 26.565 (according to andrewace3158)

while(TRUE)
{

sleep 100;// refresh view angle every 100ms

orientation= 32768 + get XZ_ATAN( get PIECE_XZ(base) - get PIECE_XZ(measure_point));
while (orientation>65535)
{orientation=orientation - 65536;
turn rotative_base to y-axis orientation speed <48>; // 0.16 * TurnRate in /units/*.fbi

view_to_show=orientation + 65536/(2*amount_of_view);
while (view_to_show>65535)
{view_to_show=view_to_show - 65536;
view_to_show=view_FD00 + view_to_show/(65536/amount_of_view);

hide view_FD00;
hide view_FD01;
hide view_FD02;
hide view_FD03;
hide view_FD04;
hide view_FD05;
hide view_FD06;
hide view_FD07;
hide view_FD08;
hide view_FD09;
hide view_FD10;
hide view_FD11;
hide view_FD12;
hide view_FD13;
hide view_FD14;
hide view_FD15;
//show view_to_show;// sadly it isn't accepted by Scriptor

if (view_to_show==view_FD00)
{show view_FD00;
if (view_to_show==view_FD01)
{show view_FD01;
if (view_to_show==view_FD02)
{show view_FD02;
if (view_to_show==view_FD03)
{show view_FD03;
if (view_to_show==view_FD04)
{show view_FD04;
if (view_to_show==view_FD05)
{show view_FD05;
if (view_to_show==view_FD06)
{show view_FD06;
if (view_to_show==view_FD07)
{show view_FD07;
if (view_to_show==view_FD08)
{show view_FD08;
if (view_to_show==view_FD09)
{show view_FD09;
if (view_to_show==view_FD10)
{show view_FD10;
if (view_to_show==view_FD11)
{show view_FD11;
if (view_to_show==view_FD12)
{show view_FD12;
if (view_to_show==view_FD13)
{show view_FD13;
if (view_to_show==view_FD14)
{show view_FD14;
if (view_to_show==view_FD15)
{show view_FD15;



Create()
{
start-script TwoDimensionnal();



SweetSpot (piecenum)
{
piecenum = view_FD00;


QueryPrimary (piecenum)
{
piecenum = firing_point;


AimFromPrimary(piecenum)
{
piecenum=base;


AimPrimary(heading, pitch)
{
signal SIG_AIM1;
set-signal-mask SIG_AIM1;
// I can't manage to get the measure_point turn with the turret, so no aiming for now
return(TRUE);



Killed(severity, corpsetype)
{
return(0);




What gives me the most trouble is getting the measure_point XZ right. For instance I had to click Use current position as Object Origin without really understanding why, and no matter what I do, the measure_point XY refuse to turn with the aiming_base, which mean the unit currently don't turn to aim.







RestoreTertiary()
	{
	sleep 8500;
	set-signal-mask 0;
	MisFlares = 0;
	signal SIG_AIM3;
	MisAdvance = 0;
	move flares to z-axis [0.0000] now;
	turn rdoor to z-axis <0.0000> speed <15.0000>;
	turn ldoor to z-axis <0.0000> speed <15.0000>;
	wait-for-turn rdoor around z-axis;
	wait-for-turn ldoor around z-axis;
	MisFlares = 1;
	return(0);
	--
	
RestoreTertiaryNow()
	{
	set-signal-mask 0;
	MisFlares = 0;
	signal SIG_AIM3;
	MisAdvance = 0;
	move flares to z-axis [0.0000] now;
	turn rdoor to z-axis <0.0000> speed <15.0000>;
	turn ldoor to z-axis <0.0000> speed <15.0000>;
	wait-for-turn rdoor around z-axis;
	wait-for-turn ldoor around z-axis;
	sleep 2800;
	MisFlares = 1;
	return(0);
	--

QueryTertiary (piecenum)
	{
	If( MisFlares == 1 )
		{
		piecenum = m1;
		return(0);
		--
	If( MisFlares == 2 )
		{
		piecenum = m2;
		return(0);
		--
	If( MisFlares == 3 )
		{
		piecenum = m3;
		return(0);
		--
	If( MisFlares == 4 )
		{
		piecenum = m4;
		return(0);
		--
	If( MisFlares == 5 )
		{
		piecenum = m5;
		return(0);
		--
	If( MisFlares == 6 )
		{
		piecenum = m6;
		return(0);
		--
	If( MisFlares == 7 )
		{
		piecenum = m1;
		return(0);
		--
	--

AimFromTertiary (piecenum)
	{
	piecenum = missiles;
	--

AimTertiary(heading, pitch)
	{
	Signal SIG_AIM3;
	set-signal-mask SIG_AIM3;
	If( !MisFlares )
		{
		sleep 200;
		--
	If( MisFlares == 7 )
		{
		MisAdvance = (MisAdvance + 1 );
		If( MisAdvance == 1 )
			{
			move flares to z-axis [-1.5000] now;
			--
		If( MisAdvance == 2 )
			{
			move flares to z-axis [-3.0000] now;
			--
		If( MisAdvance == 3 )
			{
			move flares to z-axis [-4.5000] now;
			--
		If( MisAdvance == 4 )
			{
			move flares to z-axis [-6.0000] now;
			--
		If( MisAdvance == 5 )
			{
			move flares to z-axis [-7.5000] now;
			--
		If( MisAdvance == 6 )
			{
			call-script RestoreTertiaryNow();
			--
		MisFlares = 1;
		--
	turn ldoor to z-axis <270.0000> speed <15.0000>;
	turn rdoor to z-axis <90.0000> speed <15.0000>;
	wait-for-turn ldoor around z-axis;
	wait-for-turn rdoor around z-axis;
	return(TRUE);
	--

FireTertiary()
	{
	MisFlares = ( MisFlares + 1 );
	return(0);
	--


